﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using JigLibX.Physics;
using JigLibX.Collision;
using System.Threading;

namespace WindowsGames2
{
    /// <summary>
    /// 基底 Game クラスから派生した、ゲームのメイン クラスです。
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {        
        /// <summary>
        /// アプリケーションのメイン エントリー ポイントです。
        /// </summary>
        static void Main(string[] args)
        {
            using (Game1 game = new Game1())
            {
                game.Run();
            }
        }
       // ThreadStart threadStart = new ThreadStart(run());
       // Thread newThread = new Thread(threadStart);
        KeyboardState m_KeyState;     // 現在の状態
        KeyboardState m_prevKeyState; // 前のフレームの状態
        PhysicsSystem world;//物理エンジンを初期化
        List<BoxActor> Box = new List<BoxActor>();

        public Matrix View { get; private set; }
        public Matrix Projection { get; private set; }

        BoxActor immovableBox;
        ImportEvent import = new ImportEvent();
        //===カメラ関係===//
        float _yaw;
        float _pitch;
        Vector3 _position;
        Matrix _view;
        Matrix _projection;
        //================//
        GraphicsDeviceManager graphics;

        SpriteBatch spriteBatch;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            

            InitializePhysics();//物理エンジンを有効


            this.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),
                (float)graphics.PreferredBackBufferWidth / (float)graphics.PreferredBackBufferHeight,
                0.1f,
                1000.0f
            );
        }

        /// <summary>
        /// ゲームが実行を開始する前に必要な初期化を行います。
        /// ここで、必要なサービスを照会して、関連するグラフィック以外のコンテンツを
        /// 読み込むことができます。base.Initialize を呼び出すと、使用するすべての
        /// コンポーネントが列挙されるとともに、初期化されます。
        /// </summary>
        protected override void Initialize()
        {
            // TODO: ここに初期化ロジックを追加します。

            base.Initialize();
        }
        private SpriteFont font = null;
        /// <summary>
        /// LoadContent はゲームごとに 1 回呼び出され、ここですべてのコンテンツを
        /// 読み込みます。
        /// </summary>
        protected override void LoadContent()
        {
            //this.Components.Add(new DrawEffect.Debug(this,GraphicsDevice));
            // 新規の SpriteBatch を作成します。これはテクスチャーの描画に使用できます。
            spriteBatch = new SpriteBatch(GraphicsDevice);
            // フォントをコンテンツパイプラインから読み込む
            this.font = this.Content.Load<SpriteFont>("Font");

        }
        //------------------------//
        //物理エンジン読み込み処理//
        //------------------------//
        public Boolean flat = true;
        public void InitializePhysics()
        {
            
            world = new PhysicsSystem();
            world.CollisionSystem = new CollisionSystemSAP();
            for (float x = 0; x < 3; x++)
            {
                for (float y = 0; y < 3; y++)
                {
                    for (float z = 0; z < 3; z++)
                    {
                        Box.Add(new BoxActor(this,new Vector3(x, y, z), new Vector3(0.5f, 0.5f, 0.5f)));
                    }
                }
               
            }
            this.immovableBox = new BoxActor(this, new Vector3(0, -5, 0), new Vector3(5, 2, 5));
            immovableBox.Body.Immovable = true;
            
            foreach (var s in Box) 
            {
                this.Components.Add(s);
            }

            this.Components.Add(immovableBox);
        }
        //------------------------//

        public void CameraUpdate(Matrix Views)
        {
          //  boxRenderer.SetCamera(Views,Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45),15f,0.1f,3000f));
        }

        /// <summary>
        /// UnloadContent はゲームごとに 1 回呼び出され、ここですべてのコンテンツを
        /// アンロードします。
        /// </summary>
        protected override void UnloadContent()
        {

        }

        /// <summary>
        /// ワールドの更新、衝突判定、入力値の取得、オーディオの再生などの
        /// ゲーム ロジックを、実行します。
        /// </summary>
        /// <param name="gameTime">ゲームの瞬間的なタイミング情報</param>
        /// 

        int test = 0;
        protected override void Update(GameTime gameTime)
        {
            m_prevKeyState = m_KeyState;
            m_KeyState = Keyboard.GetState();
            if (IsPressed(Keys.N))
            {
                InitializePhysics();
            }

            if (IsPressed(Keys.Escape))
            {
                this.Exit();
            }
            if (IsPressed(Keys.B))
            {
                if (test == 1)
                {
                    immovableBox.Body.Immovable = false;
                    test = 0;
                }
                else 
                {
                    immovableBox.Body.Immovable = true;
                    test = 1;
                }
            }
            Camera();

            float timeStep = (float)gameTime.ElapsedGameTime.Ticks / TimeSpan.TicksPerSecond;
            PhysicsSystem.CurrentPhysicsSystem.Integrate(timeStep);

            //world.Integrate(1.0f / 60.0f);

            base.Update(gameTime);
        }
        //-----カメラ-----//
        public void Camera() 
        {
			// マウスの移動を取得し　反映させる
			// YawはY軸を中心とした横回転
			_yaw -= (Mouse.GetState().X - GraphicsDevice.Viewport.Width / 2) / 1000f;
			// PitchはX軸を中心とした縦回転
			_pitch -= (Mouse.GetState().Y - GraphicsDevice.Viewport.Height / 2) / 1000f;
			// YawとPitchから前方の座標と左側、上側の座標を取得
			Vector3 forward =
				Vector3.TransformNormal(Vector3.Forward,
				Matrix.CreateFromYawPitchRoll(_yaw, _pitch, 0));
			Vector3 left =
				Vector3.TransformNormal(Vector3.Left,
				Matrix.CreateFromYawPitchRoll(_yaw, _pitch, 0));
			Vector3 up =
				Vector3.Up;
            // Pitchに上下の制限をかける
            _pitch = MathHelper.Clamp(_pitch,
                -MathHelper.PiOver2 + 0.01f, MathHelper.PiOver2 - 0.01f);
			// マウスを画面の中心に置く
			Mouse.SetPosition(
				GraphicsDevice.Viewport.Width / 2,
				GraphicsDevice.Viewport.Height / 2);

			// キー入力情報を取得
			KeyboardState key = Keyboard.GetState();
			if (key.IsKeyDown(Keys.W))
				_position += forward;
			if (key.IsKeyDown(Keys.S))
				_position -= forward;
			if (key.IsKeyDown(Keys.A))
				_position += left;
			if (key.IsKeyDown(Keys.D))
				_position -= left;
            if (key.IsKeyDown(Keys.Space))
                up += up;
            if (key.IsKeyDown(Keys.LeftShift))
                up -= up;
            if (key.IsKeyDown(Keys.M)) { InitializePhysics(); }

			// ビュー行列を作成
			_view = Matrix.CreateLookAt(_position, _position + forward, up);

			// プロジェクション行列は事前に設定してもよい
			_projection = Matrix.CreatePerspectiveFieldOfView(
				MathHelper.ToRadians(80f),
				GraphicsDevice.Viewport.AspectRatio,
				1f, 10000f);

            this.View = _view;
		}
        //----------------------//

        //------------------------------------//
        //マルチコアを使用し、処理を分散させる//
        //------------------------------------//
        private void run()
        {
            
            
                
            
        }

        //--------------------------------------------//
        //キーボードが押しっぱなしにならないようにする//
        //--------------------------------------------//
        public bool IsPressed(Keys key)
        {
            return (m_KeyState.IsKeyDown(key) && m_prevKeyState.IsKeyUp(key));
        }
        //-------------------------------------------//

        /// <summary>
        /// ゲームが自身を描画するためのメソッドです。
        /// </summary>
        /// <param name="gameTime">ゲームの瞬間的なタイミング情報</param>
        /// 

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: ここに描画コードを追加します。
            foreach (var s in Box) { drawBox(s); }
            
            drawBox(immovableBox);

            base.Draw(gameTime);
        }
        private void drawBox(BoxActor box)//箱を表示
        {
      //      boxRenderer.Draw(box.GetWorldTransform());
        }
    }
}
